import { computed, defineComponent, inject, reactive, ref } from "vue";
import "./editor.scss";
import EditorBlock from "./editor-block";
import deepcopy from "deepcopy";
import { useMenuDragger } from "./useMenuDragger";
import { useFocus } from "./useFocus";
import { useBlockDrag } from "./useBlockDrag";
import { useCommand } from "./useCommand";
import { $dialog } from "./DialogComponent";
import { ElButton } from "element-plus";
import { $dropdown, DropdownItem } from "./Dropdown";
import { VisualOperatorEditor } from "./visual-editor-operator";

export default defineComponent({
  props: {
    modelValue: { type: Object }, // modelValue接收v-model数据
    formData: { type: Object },
    customProps: { type: Object },
  },
  setup(props, ctx) {
    // 预览时，不能选中操作， 可以点击输入看效果
    const previewRef = ref(false);

    // 默认编辑状态，页面预览
    const editorRef = ref(true);

    const data = computed({
      get() {
        return props.modelValue;
      },
      set(newValue) {
        ctx.emit("update:modelValue", deepcopy(newValue));
      },
    });

    // 定义样式
    const containerStyles = computed(() => ({
      width: data.value.container.width + "px",
      height: data.value.container.height + "px",
    }));

    // 得到全局配置对象
    const config = inject("config");

    // 绘图区对象
    let containerRef = ref(null); // 拖动就拿到当前的容器对象
    // 菜单栏
    const { dragstart, dragend } = useMenuDragger(containerRef, data);

    // 焦点
    const { containerMousedown, blockMousedown, focusData, lastSelectBlock, clearBlockFocus, selectIndex } = useFocus(
      data,
      previewRef,
      (e) => {
        mousedown(e);
      }
    );

    // 拖拽
    const { mousedown, markLine } = useBlockDrag(focusData, lastSelectBlock, data);

    // 按钮
    const { commands } = useCommand(data, focusData);
    const buttons = [
      {
        label: "撤销",
        icon: "icon-back",
        handler: () => {
          commands.undo();
        },
      },
      {
        label: "恢复",
        icon: "icon-forward",
        handler: () => {
          commands.redo();
        },
      },
      {
        label: "导出",
        icon: "icon-export",
        handler: () => {
          $dialog({
            title: "导出json",
            content: JSON.stringify(data.value),
            footer: false,
          });
        },
      },
      {
        label: "导入",
        icon: "icon-import",
        handler: () => {
          $dialog({
            title: "导入json",
            content: "",
            footer: true,
            onConfirm(text) {
              console.log("dialog:", text);
              // data.value = JSON.parse(text);
              commands.updateContainer(JSON.parse(text));
            },
          });
        },
      },
      { label: "置顶", icon: "icon-place-top", handler: () => commands.placeTop() },
      { label: "置底", icon: "icon-place-bottom", handler: () => commands.placeBottom() },
      { label: "删除", icon: "icon-delete", handler: () => commands.delete() },
      {
        label: () => (previewRef.value ? "编辑" : "预览"),
        icon: () => (previewRef.value ? "icon-edit" : "icon-browse"),
        handler: () => {
          previewRef.value = !previewRef.value;
          // 清除选中状态
          clearBlockFocus();
        },
      },
      {
        label: "关闭",
        icon: "icon-close",
        handler: () => {
          editorRef.value = false;
          clearBlockFocus();
        },
      },
    ];

    // 选中元素
    const state = reactive({
      selectBlock: computed(() => (data.value.blocks || [])[selectIndex.value]),
      preview: false,
      editing: true,
    });

    // 右键菜单
    const onContextMenuBlock = (e, block) => {
      e.preventDefault(); // 阻止默认的右键菜单

      $dropdown({
        el: e.target, // 在哪个元素上显示菜单
        content: () => {
          return (
            <>
              <DropdownItem
                label="删除"
                icon="icon-delete"
                onClick={() => {
                  commands.delete();
                }}
              ></DropdownItem>
              <DropdownItem
                label="置顶"
                icon="icon-delete"
                onClick={() => {
                  commands.placeTop();
                }}
              ></DropdownItem>
              <DropdownItem
                label="置底"
                icon="icon-delete"
                onClick={() => {
                  commands.placeBottom();
                }}
              ></DropdownItem>
              <DropdownItem
                label="查看"
                icon="icon-delete"
                onClick={() => {
                  $dialog({
                    title: "查看节点数据",
                    content: JSON.stringify(block),
                  });
                }}
              ></DropdownItem>
              <DropdownItem
                label="导入"
                icon="icon-delete"
                onClick={() => {
                  $dialog({
                    title: "导入节点数据",
                    content: "",
                    footer: true,
                    onConfirm(text) {
                      console.log("text:", text);
                      text = JSON.parse(text);
                      commands.updateBlock(text, block);
                    },
                  });
                }}
              ></DropdownItem>
            </>
          );
        },
      });
    };

    return () =>
      !editorRef.value ? (
        <>
          <div class="editor-container-canvas__content" style={containerStyles.value}>
            {data.value.blocks.map((block, index) => (
              // <div>asfdasdfsadfasdfaf</div>
              <EditorBlock class="editor-block-preview" formData={props.formData} block={block}></EditorBlock>
            ))}
          </div>
          <div>
            <ElButton type="primary" onClick={() => (editorRef.value = true)}>
              编辑
            </ElButton>
          </div>
        </>
      ) : (
        <div class="editor">
          <div class="editor-left">
            {config.componentList.map((component) => (
              <div
                class="editor-left-item"
                draggable
                onDragstart={(e) => dragstart(e, component)}
                onDragend={(e) => dragend(e, component)}
              >
                <span>{component.label}</span>
                <div>{component.preview()}</div>
              </div>
            ))}
          </div>
          <div class="editor-top">
            {buttons.map((btn, index) => {
              const icon = typeof btn.icon == "function" ? btn.icon() : btn.icon;
              const label = typeof btn.label == "function" ? btn.label() : btn.label;
              return (
                <div class="editor-top-button" onClick={btn.handler}>
                  <i class={icon}></i>
                  <span>{label}</span>
                </div>
              );
            })}
          </div>
          <div class="editor-right">
            <VisualOperatorEditor
              block={state.selectBlock}
              dataModel={data}
              formData={props.formData}
              updateBlock={commands.updateBlock}
              updateModelValue={commands.updateModelValue}
            ></VisualOperatorEditor>
          </div>
          <div class="editor-container">
            <div class="editor-container-canvas">
              <div
                class="editor-container-canvas__content"
                ref={containerRef}
                onmousedown={containerMousedown}
                style={containerStyles.value}
              >
                {data.value.blocks.map((block, index) => (
                  // 显示组件配置区域
                  <EditorBlock
                    block={block}
                    customProps={props.customProps}
                    formData={props.formData}
                    class={{
                      "editor-block-focus": block.focus,
                      "editor-block-preview": previewRef.value,
                    }}
                    onmousedown={(e) => blockMousedown(e, block, index)}
                    oncontextmenu={(e) => onContextMenuBlock(e, block)}
                  ></EditorBlock>
                ))}
                {markLine.x !== null && <div class="line-x" style={{ left: markLine.x + "px" }}></div>}
                {markLine.y !== null && <div class="line-y" style={{ top: markLine.y + "px" }}></div>}
              </div>
            </div>
          </div>
        </div>
      );
  },
});
